/*
 * LoopMediaReader.cpp
 *
 *  Created on: 2021年5月7日
 *      Author: chuanjiang.zh
 */

#include "LoopMediaReader.h"
#include "FfmpegUtil.h"


LoopMediaReader::LoopMediaReader(UMediaReader* reader, bool owned, int count)
	: m_reader(reader)
	, m_owned(owned)
	, m_count(count)
	, m_opened()
	, m_state(UMEDIA_STATE_CLOSED)
	, m_curCount()
	, m_tsOffset()
	, m_retryInterval(1000)
{
}

LoopMediaReader::~LoopMediaReader()
{
	close();

	if (m_owned)
	{
		delete m_reader;
		m_reader = nullptr;
	}
}

int LoopMediaReader::getCount()
{
	return m_count;
}

void LoopMediaReader::setCount(int count)
{
	m_count = count;
}

void LoopMediaReader::setRetryInterval(int ms)
{
	if (ms > 0)
	{
		m_retryInterval = ms;
	}
}

int LoopMediaReader::open(const char* url, const char* params)
{
	m_url = url;
	m_params = params;

	if (isOpen())
	{
		close();
	}

	m_opened = true;

	int ret = m_reader->open(url, params);
	if (ret == 0)
	{
		m_reader->getFormat(m_format);
	}

	return ret;
}

void LoopMediaReader::close()
{
	if (!m_opened)
	{
		return;
	}

	m_opened = false;

	m_reader->close();

}

bool LoopMediaReader::isOpen()
{
	return m_opened;
}

bool LoopMediaReader::getFormat(UMediaFormat& fmt)
{
	if (!m_opened)
	{
		return false;
	}

	fmt = m_format;
	return m_opened;
}

int LoopMediaReader::getDuration()
{
	if (m_count < 0)
	{
		return 0;
	}

	return m_format.m_duration * m_count;
}

bool LoopMediaReader::play()
{
	setState(UMEDIA_STATE_PLAYING);
	return true;
}

bool LoopMediaReader::pause()
{
	setState(UMEDIA_STATE_PAUSED);
	return true;
}

void LoopMediaReader::stop()
{
	setState(UMEDIA_STATE_STOPPED);
}

int LoopMediaReader::getState()
{
	std::lock_guard< std::mutex > lock(m_mutex);
	return m_state;
}

bool LoopMediaReader::seekable()
{
	return m_count == 1;
}

bool LoopMediaReader::seek(int64_t offset)
{
	return m_reader->seek(offset);
}

int64_t LoopMediaReader::getTime()
{
	return m_tsOffset + m_reader->getTime();
}

bool LoopMediaReader::setScale(float scale)
{
	return m_reader->setScale(scale);
}

float LoopMediaReader::getScale()
{
	return m_reader->getScale();
}

int LoopMediaReader::read(UMediaPacket& pkt)
{
	int ret = m_reader->read(pkt);
	if (ret == 0)
	{
		pkt.set_dts(pkt.dts() + m_tsOffset);
		pkt.set_pts(pkt.pts() + m_tsOffset);

		return ret;
	}

	if (ret == EAGAIN || ret == AVERROR(EAGAIN))
	{
		return ret;
	}

	m_curCount++;

	if (m_count > 0 && m_curCount >= m_count)
	{
		return AVERROR_EOF;
	}

	m_tsOffset += m_reader->getTime();

	// reopen
	m_reader->close();

	if (m_eventDelay.timedwait(m_retryInterval))
	{
		return EAGAIN;
	}

	int rc = m_reader->open(m_url.c_str(), m_params.c_str());

	ret = EINTR;

	return ret;
}

void LoopMediaReader::interrupt()
{
	m_eventDelay.post();

	m_reader->interrupt();
}

bool LoopMediaReader::isLive()
{
	if (m_count < 0)
	{
		return false;
	}

	return m_reader->isLive();
}

const char* LoopMediaReader::getFormatName()
{
	return m_reader->getFormatName();
}

size_t LoopMediaReader::getMetaData(const char* name, char* value, size_t size)
{
	return m_reader->getMetaData(name, value, size);
}

void LoopMediaReader::setState(UMediaState state)
{
	std::lock_guard< std::mutex > lock(m_mutex);
	m_state = state;
}